package com.ruoyi.web.controller;

import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.annotation.RepeatSubmit;
import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.page.PageDomain;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.page.TableSupport;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.framework.web.exception.TadpoleException;
import com.ruoyi.web.domain.AppUser;
import com.ruoyi.web.dto.AppUserAddressBindDTO;
import com.ruoyi.web.dto.AppUserBindIdentityDTO;
import com.ruoyi.web.dto.AppUserCompleteDTO;
import com.ruoyi.web.dto.AppUserLoginAddressDTO;
import com.ruoyi.web.dto.AppUserLoginPasswordDTO;
import com.ruoyi.web.dto.AppUserRegisterDTO;
import com.ruoyi.web.dto.UpdateUserDto;
import com.ruoyi.web.service.IAppUserService;
import com.ruoyi.web.vo.AppLoginResVO;
import com.ruoyi.web.vo.AppUserDetailVO;
import com.ruoyi.web.vo.AppUserVO;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.BeanUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * app用户Controller
 *
 * @author ruoyi
 * @date 2022-12-28
 */
@RestController
@RequestMapping("/user")
public class AppUserController extends BaseController {
    private final IAppUserService appUserService;

    public AppUserController(IAppUserService appUserService) {
        this.appUserService = appUserService;
    }

    @GetMapping("/detail")
    public R<AppUserDetailVO> getAppUserDetail() {
        return appUserService.getAppUserDetail();
    }

    /**
     * 注册
     *
     * @param dto dto
     * @return {@link R< AppLoginResVO>}
     * @since 2023/3/20 15:14
     */
    @Anonymous
    @RepeatSubmit
    @PostMapping("/register")
    public R<AppLoginResVO> register(@RequestBody AppUserRegisterDTO dto) {
        AppLoginResVO res = appUserService.register(dto);
        return R.ok(res);
    }

    /**
     * 通过地址登陆
     *
     * @param dto dto
     * @return {@link R< AppLoginResVO>}
     * @since 2023/3/20 15:14
     */
    @Anonymous
    @RepeatSubmit
    @PostMapping("/login/address")
    public R<AppLoginResVO> loginByAddress(@RequestBody AppUserLoginAddressDTO dto) {
        AppLoginResVO res = appUserService.loginByAddress(dto);
        return R.ok(res);
    }

    /**
     * 通过手机号、密码登陆
     *
     * @param dto dto
     * @return {@link R< AppLoginResVO>}
     * @since 2023/3/20 15:14
     */
    @Anonymous
    @RepeatSubmit
    @PostMapping("/login/password")
    public R<AppLoginResVO> loginByPassword(@RequestBody AppUserLoginPasswordDTO dto) {
        AppLoginResVO res = appUserService.loginByPassword(dto);
        return R.ok(res);
    }

    /**
     * 旧用户完善信息
     *
     * @param dto dto
     * @return {@link R< AppUserDetailVO>}
     * @since 2023/3/20 15:14
     */
    @RepeatSubmit
    @PostMapping("/complete")
    public R<AppUserDetailVO> complete(@RequestBody AppUserCompleteDTO dto) {
        AppUserDetailVO res = appUserService.complete(dto);
        return R.ok(res);
    }

    /**
     * 浏览器注册用户绑定地址
     *
     * @param dto dto
     * @return {@link R< AppUserDetailVO>}
     * @since 2023/3/20 15:14
     */
    @RepeatSubmit
    @PostMapping("/address/bind")
    public R<AppUserDetailVO> addressBind(@RequestBody AppUserAddressBindDTO dto) {
        AppUserDetailVO res = appUserService.addressBind(dto);
        return R.ok(res);
    }

    /**
     * 查询app用户列表
     */
    @PreAuthorize("@ss.hasPermi('web:user:list')")
    @GetMapping("/list")
    public TableDataInfo list(AppUser appUser) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if (loginUser.getUser().getRoles().get(0).getRoleId() == 3) {
            // 获取所有子集
            List<AppUser> userList = new ArrayList<>();
            appUserService.getAllChild(userList, loginUser.getUserId());

            // 根据查询条件过滤
            userList = userList.stream()
                    .filter(i -> {
                        // 没有任何查询条件
                        if (Objects.isNull(appUser.getId())
                                && Objects.isNull(appUser.getVipLevel())
                                && Strings.isBlank(appUser.getPhone())
                                && Strings.isBlank(appUser.getEmail())
                                && Strings.isBlank(appUser.getAddress())) {
                            return true;
                        }

                        return !Objects.isNull(appUser.getId()) && appUser.getId().equals(i.getId())
                                || !Objects.isNull(appUser.getVipLevel()) && appUser.getVipLevel().equals(i.getVipLevel())
                                || Strings.isNotBlank(appUser.getPhone()) && Strings.isNotBlank(i.getPhone()) && i.getPhone().contains(appUser.getPhone())
                                || Strings.isNotBlank(appUser.getEmail()) && Strings.isNotBlank(i.getEmail()) && i.getEmail().contains(appUser.getEmail())
                                || Strings.isNotBlank(appUser.getAddress()) && Strings.isNotBlank(i.getAddress()) && i.getAddress().contains(appUser.getAddress());
                    })
                    .collect(Collectors.toList());

            // 手动分页
            PageDomain pageDomain = TableSupport.buildPageRequest();
            Integer pageNum = pageDomain.getPageNum();
            Integer pageSize = pageDomain.getPageSize();
            TableDataInfo rspData = new TableDataInfo();
            rspData.setTotal(userList.size());
            if (pageNum * pageSize <= userList.size()) {
                userList = userList.subList((pageNum - 1) * pageSize, pageNum * pageSize);
            } else {
                userList = userList.subList((pageNum - 1) * pageSize, userList.size());
            }
            List<AppUserVO> voList = new ArrayList<>();
            for (AppUser user : userList) {
                AppUserVO vo = new AppUserVO();
                BeanUtils.copyProperties(user, vo);
                voList.add(vo);
            }
            rspData.setCode(HttpStatus.SUCCESS);
            rspData.setMsg("查询成功");
            rspData.setRows(voList);
            return rspData;
        } else {
            startPage();
            List<AppUser> list = appUserService.selectAppUserList(appUser);
            TableDataInfo info = getDataTable(list);

            List<AppUserVO> voList = new ArrayList<>();
            for (AppUser user : list) {
                AppUserVO vo = new AppUserVO();
                BeanUtils.copyProperties(user, vo);
                voList.add(vo);
            }
            return getDataTable(info, list);
        }
    }

    @PostMapping("/change/email")
    public R<String> updateEmail(@RequestBody UpdateUserDto dto) {
        return appUserService.updateEmail(dto);
    }

    /**
     * 导出app用户列表
     */
    @PreAuthorize("@ss.hasPermi('web:user:export')")
    @Log(title = "app用户", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, AppUser appUser) {
        List<AppUser> list = appUserService.selectAppUserList(appUser);
        ExcelUtil<AppUser> util = new ExcelUtil<AppUser>(AppUser.class);
        util.exportExcel(response, list, "app用户数据");
    }

    /**
     * 获取app用户详细信息
     */
    @PreAuthorize("@ss.hasPermi('web:user:query')")
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id) {
        AppUser user = appUserService.selectAppUserById(id);
        if (Objects.isNull(user)) {
            throw new TadpoleException("未能查询到用户信息，userId：" + id);
        }

        AppUserVO vo = new AppUserVO();
        BeanUtils.copyProperties(user, vo);
        return success(vo);
    }

    /**
     * 新增app用户
     */
    @PreAuthorize("@ss.hasPermi('web:user:add')")
    @Log(title = "app用户", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody AppUser appUser) {
        return toAjax(appUserService.insertAppUser(appUser));
    }

    /**
     * 修改app用户
     */
    @PreAuthorize("@ss.hasPermi('web:user:edit')")
    @Log(title = "app用户", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody AppUser appUser) {
        return toAjax(appUserService.updateAppUser(appUser));
    }

    /**
     * 删除app用户
     */
    @PreAuthorize("@ss.hasPermi('web:user:remove')")
    @Log(title = "app用户", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable Long[] ids) {
        return toAjax(appUserService.deleteAppUserByIds(ids));
    }

    /**
     * 绑定身份证信息
     *
     * @param dto dto
     * @return {@link AjaxResult}
     * @since 2023/3/29 12:23
     */
    @PutMapping("/bind/identity")
    public AjaxResult bindIdentity(@RequestBody AppUserBindIdentityDTO dto) {
        appUserService.bindIdentity(dto);
        return success();
    }

    /**
     * h5查询下级
     *
     * @return {@link TableDataInfo}
     * @since 2023/3/28 20:53
     */
    @GetMapping("/app/page/child")
    public TableDataInfo appPageChild() {
        List<AppUserVO> list = appUserService.appListChild();

        // 手动分页
        PageDomain pageDomain = TableSupport.buildPageRequest();
        Integer pageNum = pageDomain.getPageNum();
        Integer pageSize = pageDomain.getPageSize();
        TableDataInfo rspData = new TableDataInfo();
        rspData.setTotal(list.size());
        if (pageNum * pageSize <= list.size()) {
            list = list.subList((pageNum - 1) * pageSize, pageNum * pageSize);
        } else {
            list = list.subList((pageNum - 1) * pageSize, list.size());
        }

        return getDataTable(list);
    }
}
